/*
 * chapter_10.cpp
 *
 *  Created on: 2020年11月23日
 *      Author: san
 */

#include <algorithm>
#include <iostream>
#include <vector>
#include <string>
#include <list>
#include <numeric>
#include <functional>
#include <iterator>
#include <fstream>

using namespace std::placeholders;

using std::string;

int t10_1()
{
	std::vector<int> ivec{1,2,3,4,5,1,34,1,31,1,1,1,1,1,13,4,1};

	int result = count(ivec.cbegin(), ivec.cend(), 1);
	std::cout << "count of 1: " << result << std::endl;
}

int t10_3()
{

	std::vector<int> ivec{1, 2, 3, 4, 4, 5, 5, 6, 7, 7};
	std::cout << "sum: " << accumulate(ivec.begin(), ivec.end(), 1) << std::endl;
	return 0;
}

int t10_4()
{


	std::vector<double> ivec{1.1, 2.9, 3.14, 4.45, 4.13, 5.3, 5.24, 6.4, 7.0, 7.1};
	std::cout << "sum: " << accumulate(ivec.begin(), ivec.end(), 1.1) << std::endl;  // 若第三个参数为int，会造成精度丢失
	return 0;
}

int t10_5()
{

	const char *s0 = "hello world!";
	const char *s1("hello world!");
	std::cout << std::equal(s0, s0 + 11, s1) << std::endl;
	return 0;
}


int t10_6()
{
	int a[10];
	std::fill_n(std::begin(a), 10, 0);
	std::fill_n(std::begin(a), 5, 1);
	for (int i = 0; i < 10; ++i)
	{
		std::cout << a[i] << " ";
	}
	std::cout << std::endl;
	return 0;
}

int t10_7()
{

	std::vector<int> ivec;
	ivec.resize(5);   // reserve改变容量，不改变size， 注意这两的区别
	std::list<int> lst{1, 2, 3, 4, 5};
	copy(lst.begin(), lst.end(), ivec.begin());

	for (int i: ivec)
	{
		std::cout << i << " ";
	}
	std::cout << std::endl;
	return 0;
}


void elimDups(std::vector<std::string> &svec)
{
	// 先对svec进行排序
	sort(svec.begin(), svec.end());
	for (std::string s: svec)
	{
		std::cout << s << " ";
	}

	std::cout << std::endl;
	// unique重排输入范围，使得每个单词只出现一次
	// 排列在范围的前部，返回指向不重复区域之后一个位置的迭代器
	auto end_unique = unique(svec.begin(), svec.end());
	// 使用向量操作erase删除重复的单词
	svec.erase(end_unique, svec.end());
}

int t10_9()
{

	std::vector<std::string> svec{"Hello", "World!", "Jim", "Jim", "Tom", "hello", "alibaba", "Alibaba", "tx"};
	std::cout << std::endl;

	elimDups(svec);

	for (std::string s: svec)
	{
		std::cout << s << " ";
	}
	return 0;
}

bool isShorter2(const string &s1, const string &s2)
{
	return s1.size() < s2.size();
}


void elimDups(std::vector<std::string> &svec, bool (*pf)(const string &s1, const string &s2))
{
	// 先对svec进行排序
	sort(svec.begin(), svec.end(), pf);
	for (std::string s: svec)
	{
		std::cout << s << " ";
	}

	std::cout << std::endl;
	// unique重排输入范围，使得每个单词只出现一次
	// 排列在范围的前部，返回指向不重复区域之后一个位置的迭代器
	auto end_unique = unique(svec.begin(), svec.end());
	// 使用向量操作erase删除重复的单词
	svec.erase(end_unique, svec.end());
}

int t10_11()
{

	bool isShorter2(const string &s1, const string &s2);
	bool (*pf)(const string &s1, const string &s2) = isShorter2;
	std::vector<std::string> svec{"Hello", "World!", "Jim", "Jim", "Tom", "hello", "alibaba", "Alibaba", "tx"};

	elimDups(svec, pf);
	for (std::string s: svec)
	{
		std::cout << s << " ";
	}
	return 0;
}

int t10_14()
{
	auto sum = [](const int a, const int b) { return a+b; };  // 定义匿名函数
	return 0;
}

void bigges(std::vector<string> &words, std::vector<string>::size_type sz)
{
	elimDups(words);  // 将words按字典序排序，删除重复单词

	// 长度相同的单词维持字典序
	std::stable_sort(words.begin(), words.end(), [](const string &s1, const string &s2){ return s1.size() < s2.size();});

	// 获取一个迭代器，指向第一个size > sz 的元素
	auto wc = std::find_if(words.begin(), words.end(), [sz](const string &s) { return s.size() > sz; });

	// 计算 size > sz 的元素的数目
	auto count = words.end() - wc;
	std::cout << "count: " << count << " " << std::endl;

	// 打印长度大与指定值的word
	std::for_each(wc, words.end(), [](const string &s){ std::cout << s << " "; });

}

int t10_16()
{
	std::vector<std::string> svec{"Hello", "World!", "Jim", "Jim", "Tom", "hello", "alibaba", "Alibaba", "tx"};
	bigges(svec, 4);
	return 0;
}

void bigges2(std::vector<string> &words, std::vector<string>::size_type sz)
{
	elimDups(words);  // 将words按字典序排序，删除重复单词

	// 长度相同的单词维持字典序
	std::stable_sort(words.begin(), words.end(), [](const string &s1, const string &s2){ return s1.size() < s2.size();});

	// 使用patition代替find_if
	auto wc = std::partition(words.begin(), words.end(), [sz](const string &s){ return s.size() < sz;});


	// 计算 size > sz 的元素的数目
	auto count = words.end() - wc;
	std::cout << "count: " << count << " " << std::endl;

	// 打印长度大与指定值的word
	std::for_each(wc, words.end(), [](const string &s){ std::cout << s << " "; });
}

int t10_18()
{
	std::vector<std::string> svec{"Hello", "World!", "Jim", "Jim", "Tom", "hello", "alibaba", "Alibaba", "tx"};
	bigges2(svec, 4);
	return 0;
	return 0;
}

int t10_21()
{
	int i = 10;
	auto equal_zero = [&i]() -> bool
			{ --i ;return 0 == i ? true: false; };
	return 0;
}

bool smaller(string s, string::size_type sz)
{
	return s.size() < sz;
}

void smalles(std::vector<string> &svec, string::size_type sz)
{
	auto bsmaller = bind(smaller, _1, sz);
	auto wc = std::partition(svec.begin(), svec.end(), bsmaller);
	std::for_each(svec.begin(), wc, [](const string &s){ std::cout << s << " "; });
}

int t10_22()
{
	std::vector<std::string> svec{"Hello", "World!", "Jim", "Jim", "Tom", "hello", "alibaba", "Alibaba", "tx"};
	smalles(svec, 4);
	return 0;
}

int t10_27()
{
	/*
	 * 使用unique_copy
	 */
	std::vector<std::string> svec{"Hello", "World!", "Jim", "Jim", "Tom", "hello", "alibaba", "Alibaba", "tx"};
	std::list<string> slt(15);  // 要预留空间，不然会报错
	std::unique_copy(svec.begin(), svec.end(), slt.begin());

	std::for_each(slt.begin(), slt.end(), [](const string &s){ std::cout << s << " "; });
	return 0;
}

void testStreamIterator()
{
	std::ifstream in("/home/san/eclipse-workspace/CppPrimer/Sources/a.txt");
	std::istream_iterator<string> init_it(in);
	std::istream_iterator<string> eof;
	std::vector<string> svec(init_it, eof);

	std::cout << "svec.size(): " << svec.size() << std::endl;
	std::for_each(svec.begin(), svec.end(), [](const string &s){ std::cout << s << " ";});
}

void t10_31()
{
	/*
	 * 从标准输入流读去数据传给输出流，并去重
	 */
	std::istream_iterator<int> init_it(std::cin), eof;
	std::ostream_iterator<int> iter_out(std::cout, "\n");

	std::unique_copy(init_it, eof, iter_out);
}

void t10_37()
{
	std::vector<int> ivec{1,2,3,4,5,6,7,8,9,10};
	std::list<int> ils(5);
	ils.assign(ivec.rbegin() + 3, ivec.rend() - 2);
	std::for_each(ils.begin(), ils.end(), [](const int &i){ std::cout << i << " ";});
}

void t10_42()
{
	std::list<std::string> slst{"Hello", "World!", "Jim", "Jim", "Tom", "hello", "alibaba", "Alibaba", "tx"};
	slst.unique();
	std::for_each(slst.begin(), slst.end(), [](const string &s){ std::cout << s << " "; });
}

int main10()
{
	std::cout << "-----------------初识泛型算法--------------" << std::endl;
	t10_1();
	t10_3();
	t10_4();  // 若第三个参数为int，会造成精度丢失
	t10_5();  // 指针也是迭代器

	std::cout << "-----------------写容器元素的算法--------------" << std::endl;
	t10_6();
	t10_7();

	std::cout << "-----------------重排容器元素的算法--------------" << std::endl;
	t10_9();
	std::cout << std::endl << "-------------------向算法传递函数-------------------" << std::endl;
	t10_11();

	std::cout << std::endl <<  "-----------------lambda函数--------------" << std::endl;
	t10_14();
	t10_16();
	t10_18();

	std::cout << std::endl <<  "-----------------lambda的捕获与返回--------------" << std::endl;
	t10_21();

	std::cout << std::endl <<  "-----------------bind参数绑定----------------" << std::endl;
	t10_22();

	std::cout << std::endl <<  "-----------------再探迭代器----------------" << std::endl;
	t10_27();
//	t10_28();

	// 流迭代器
	testStreamIterator();
//	t10_31();
	std::cout << std::endl;

	// 反迭代器、
	t10_37();
	t10_42();
	std::cout << std::endl;

	// 特定容器操作  链表
	t10_42();

	return 0;
}


